package com.zhentao.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhentao.mapper.TbMenuMapper;
import com.zhentao.mapper.TbRoleMapper;
import com.zhentao.mapper.TbUserRoleMapper;
import com.zhentao.mapper.UserInfoMapper;
import com.zhentao.model.common.dtos.PermissionResult;
import com.zhentao.model.common.dtos.ResponseResult;
import com.zhentao.model.common.enums.AppHttpCodeEnum;
import com.zhentao.model.common.enums.RedisConstants;
import com.zhentao.model.common.pojo.management.TbMenu;
import com.zhentao.model.common.pojo.management.TbRole;
import com.zhentao.model.common.pojo.management.TbUserRole;
import com.zhentao.model.common.pojo.management.UserInfo;
import com.zhentao.model.common.pojo.management.dto.req.SysUserDto;
import com.zhentao.model.common.pojo.users.param.UserInfoDto;
import com.zhentao.service.IUserInfoService;
import com.zhentao.userLocal.AdminUserThreadLocalUtils;
import com.zhentao.util.AdminUserPermissionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import utils.JwtService;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.zhentao.enums.AdminPermsEnum.SYS_COUPON_SELECT;
import static com.zhentao.model.common.enums.AppHttpCodeEnum.SERVER_ERROR;
import static com.zhentao.model.common.enums.RedisConstants.SYS_PERMISSION_LIST_CACHE_KEY;
import static com.zhentao.model.common.enums.RedisConstants.SYS_USER_LOGIN_CACHE_KEY;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author mp
 * @since 2025-01-03
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements IUserInfoService {

    @Resource
    private TbRoleMapper roleMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Resource
    private TbMenuMapper permissionMapper;
    //    @Resource
//    private ChargeUserFeignApi userFeignApi;
//    @Resource
//    private ChargeUserFeignApi chargeUserFeignApi;
//    @Autowired
//    private RedisIdWorker redisIdWorker;
    @Resource
    private TbUserRoleMapper sysUserRoleMapper;
    @Resource
    private UserInfoMapper userMapper;
    @Resource
    private TbUserRoleMapper userRoleMapper;

    /**
     * @return com.zhentao.model.common.dtos.ResponseResult
     * @description admin -- user -- login
     * @author mhy
     * @date 2024/12/26 19:20
     */
    @Override
    public ResponseResult login(SysUserDto sysUser) {
        // 判断参数是否有效
        if (sysUser == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 判断该用户是否存在
        UserInfo user = getOne(Wrappers.<UserInfo>lambdaQuery()
                .eq(StringUtils.checkValNotNull(sysUser.getUserName()), UserInfo::getUserName, sysUser.getUserName()));
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CHARGE_USER_DATA_NOT_EXIST);
        }
        // 判断是否加入黑名单
        if (user.getStatus() == 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CHARGE_USER_STATUS_ERROR);
        }
        // 密码加盐加密
        boolean b = BCrypt.checkpw(sysUser.getPassword(), user.getPassword());
        // 验证密码是否正确
        if (!b) {
            return ResponseResult.errorResult(AppHttpCodeEnum.LOGIN_PASSWORD_ERROR);
        }
        // 创建Dto
        SysUserDto dto = setUserDtoAttribute(user);
        Map<String, Object> map = BeanUtil.beanToMap(dto, new HashMap<>()
                , CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName, fieldValue) -> {
                            {
                                // 如果 fieldValue 为 null，返回空字符串或者其他合适的默认值
                                return fieldValue != null ? fieldValue.toString() : user.getId();
                            }
                        }));
        // 存放在redis中
        redisTemplate.opsForValue().set(SYS_USER_LOGIN_CACHE_KEY + user.getId(), JSON.toJSONString(map));
        redisTemplate.expire(RedisConstants.SYS_USER_LOGIN_CACHE_EXPIRE_TIME + user.getId(), 30, TimeUnit.MINUTES);
        // 存放全局管理端id 用作工具类 获取用户id
        redisTemplate.opsForValue().set(RedisConstants.SYS_USER_LOGIN_CACHE_KEY_ID, user.getId().toString());
        redisTemplate.expire(RedisConstants.SYS_USER_LOGIN_CACHE_KEY_ID, 30, TimeUnit.MINUTES);
        // 生成token
        String token = JwtService.createToken(map);
        return ResponseResult.okResult(token);
    }

    /**
     * @param user
     * @return com.zhentao.model.admin.dto.SysUserDto
     * @description 对 userDto 对象设置属性值
     * @author mhy
     * @date 2024/12/26 20:15
     */
    private SysUserDto setUserDtoAttribute(UserInfo user) {
        SysUserDto dto = new SysUserDto();

        BeanUtils.copyProperties(user, dto);
        dto.setId(user.getId());
        dto.setPassword("");

        TbRole role = roleMapper.selectUserRole(user.getId());

        // 获取用户权限字符串
        List<String> perms = new ArrayList<>();
        List<TbMenu> permissions = permissionMapper.selectMenuByUserIds(user.getId());
        if (permissions != null && permissions.size() > 0) {
            for (TbMenu permission : permissions) {
                if (!org.springframework.util.StringUtils.isEmpty(permission)) {
                    perms.add(permission.getPerm());
                }
            }
        }
        redisTemplate.opsForValue().set(SYS_PERMISSION_LIST_CACHE_KEY + user.getId(), JSON.toJSONString(perms));
        return dto;
    }

    /**
     * @param
     * @return com.zhentao.model.common.dtos.ResponseResult
     * @description 获取用户信息
     * @author mhy
     * @date 2024/12/26 20:51
     */
    @Override
    public ResponseResult userInfo() {
        UserInfo user = AdminUserThreadLocalUtils.getUserInfo();
        if (StringUtils.checkValNull(user)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CHARGE_USER_DATA_NOT_EXIST);
        }
        UserInfo userById = getById(user.getId());
        // 查询用户对应的角色
        TbRole role = roleMapper.selectUserRole(user.getId());
        if (org.springframework.util.StringUtils.isEmpty(role)) return ResponseResult.errorResult(SERVER_ERROR);
        SysUserDto dto = new SysUserDto();
//        dto.setAvatar(userById.get());
        dto.setUserName(userById.getUserName());
        dto.setRoleName(role.getRoleName());
        return ResponseResult.okResult(dto);
    }

    /**
     * @param
     * @return com.zhentao.model.common.dtos.ResponseResult
     * @description 退出登录
     * @author 振涛教育_小Q
     * @date 2024/12/27 8:58
     */
    @Override
    public ResponseResult logout() {
        // 获取登录用户
        UserInfo user = AdminUserThreadLocalUtils.getUserInfo();
        if (org.springframework.util.StringUtils.isEmpty(user)) {
            return ResponseResult.errorResult(AppHttpCodeEnum.CHARGE_USER_DATA_NOT_EXIST);
        }
        // 删除redis中的缓存
        Boolean delete = redisTemplate.delete(SYS_USER_LOGIN_CACHE_KEY + user.getId());
        // 删除用户的权限字符串
        redisTemplate.delete(SYS_PERMISSION_LIST_CACHE_KEY + user.getId());

        return Boolean.TRUE.equals(delete) ? ResponseResult.okResult(200000, "登出成功") : ResponseResult.errorResult(400, "登出失败");
    }

    @Override
    /**
     * @description:获取用户信息列表
     * @author: muhaoyang
     * @date: 2025/1/3 16:35
     * @param: [chargeUser]
     * @return: com.zhentao.model.common.dtos.PermissionResult
     **/
    public PermissionResult getUserList(String userName) {
        TbRole role = getRole();
        if (role.getRoleName().equals("超级管理员") || role.getRoleName().equals("管理员")) {
            List<UserInfo> list = this.list(Wrappers.<UserInfo>lambdaQuery().eq(StringUtils.checkValNotNull(userName), UserInfo::getUserName, userName));

            list.forEach(userInfo -> {
                userInfo.setPassword("******");
                Integer id = userInfo.getId();
                //查询角色id
                TbUserRole tbUserRole = sysUserRoleMapper.selectOne(Wrappers.<TbUserRole>lambdaQuery().eq(TbUserRole::getUserId, id));
                //设置角色id
                if (tbUserRole != null) {
                    userInfo.setRoleId(tbUserRole.getRoleId());
                }
            });


            return PermissionResult.OK(200000, "获取成功", list);
        }
        return PermissionResult.ERROR(400, "您没有权限");
    }

    @Override
    public PermissionResult csRun() {
        // 获取权限
        AdminUserPermissionUtils permissionUtils = new AdminUserPermissionUtils(redisTemplate);
        ResponseResult result = permissionUtils.hasPermission(SYS_COUPON_SELECT);
        if (!(result.getCode() == 200000)) {
            return PermissionResult.ERROR(result.getCode(), result.getErrorMessage());
        }
        return PermissionResult.OK(result.getCode(), result.getErrorMessage());
    }

    @Override
    @Transactional
    public PermissionResult updateUser(UserInfoDto dto) {
        TbRole role = getRole();
        if(!role.getRoleName().equals("超级管理员")){
            return PermissionResult.ERROR(400, "您没有权限");
        }
        //判断参数
        if (dto == null) {
            return PermissionResult.ERROR(400, "参数错误");
        }
        // 判断用户是否存在
        Integer id = dto.getId();
        UserInfo user = this.getById(id);
        if (user == null) {
            return PermissionResult.ERROR(400, "用户不存在");
        }
        // 判断用户是否是黑名单
        if (user.getStatus() == 0) {
            return PermissionResult.ERROR(400, "用户已加入黑名单");
        }

        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(dto, userInfo);
        // 执行添加
        boolean save = this.updateById(userInfo);
        // 修改用户的角色
        Integer id1 = userInfo.getId();

        TbUserRole userRole = sysUserRoleMapper.selectOne(Wrappers.<TbUserRole>lambdaQuery().eq(TbUserRole::getUserId, id1).eq(TbUserRole::getRoleId, dto.getRoleId()));
        if (userRole != null) {
            return PermissionResult.ERROR(400, "该用户已经拥有该角色,不可重复添加");
        }
        TbUserRole tbUserRole = new TbUserRole();
        tbUserRole.setUserId(id1);
        tbUserRole.setRoleId(dto.getRoleId());
        int insert1 = sysUserRoleMapper.insert(tbUserRole);
        return PermissionResult.OK(200000, "添加成功");
    }

    @Override
    public PermissionResult getRoleList() {
        TbRole sysRole = getRole();
        List<TbRole> sysRoles = new ArrayList<>();
        if (sysRole.getRoleName().equals("超级管理员")) {
            sysRoles = roleMapper.selectList(null);
        }
        if (sysRole.getRoleName().equals("运营人")) {
            return PermissionResult.OK(200000, "您没有权限", null);
        }
        if (sysRole.getRoleName().equals("管理员")) {
            sysRoles = roleMapper.selectList(Wrappers.<TbRole>lambdaQuery().ne(TbRole::getRoleName, "超级管理员"));
        }
        return PermissionResult.OK(200000, "查询成功", sysRoles);
    }

    @Override
    public ResponseResult registry(UserInfoDto userInfoDto) {
        TbRole tbRole = getRole();
        if(!tbRole.getRoleName().equals("超级管理员") ){
            return ResponseResult.errorResult(400, "您没有权限");
        }
        UserInfo userInfo = new UserInfo();
        //获取用户名 并判断是否重复
        String userName = userInfoDto.getUserName();
        if (userName != null && userName.length() > 0) {
            LambdaQueryWrapper<UserInfo> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserInfo::getUserName, userName);
            UserInfo one = this.getOne(wrapper);
            if (one != null) {
                return ResponseResult.errorResult(400, "用户名已存在");
            }
        }
        // 拷贝
        BeanUtils.copyProperties(userInfoDto, userInfo);
        // 给密码加盐加密
        userInfo.setPassword(BCrypt.hashpw(userInfo.getPassword(), BCrypt.gensalt()));
        userInfo.setCreateTime(LocalDateTime.now());
        boolean b = this.save(userInfo);
        if (b) {
            Integer id = userInfo.getId();
            // 获取角色
            Integer roleId = userInfoDto.getRoleId();

            TbUserRole tbUserRole = new TbUserRole();
            tbUserRole.setUserId(id);
            tbUserRole.setRoleId(roleId);
            // 添加到数据库
            userRoleMapper.insert(tbUserRole);

        }
        return ResponseResult.okResult("添加成功");
    }
    // 获取角色
    private TbRole getRole() {
        UserInfo sysUser = AdminUserThreadLocalUtils.getUserInfo();

        TbUserRole userRole = sysUserRoleMapper.selectOne(Wrappers.<TbUserRole>lambdaQuery()
                .eq(TbUserRole::getUserId, sysUser.getId()));
        TbRole tbRole = roleMapper.selectOne(Wrappers.<TbRole>lambdaQuery().eq(TbRole::getId, userRole.getRoleId()));
        return tbRole;
    }

    @Override
    /**
     * @description:将用户加入黑名单
     * @author: muhaoyang
     * @date: 2025/1/6 10:07
     * @param: [userId]
     * @return: com.zhentao.model.common.dtos.PermissionResult
     **/
    public PermissionResult addBlackList(Integer userId) {
        //判断参数
        if (userId == null) {
            return PermissionResult.ERROR(400, "参数错误");
        }
        TbRole role = getRole();
        if (role.getRoleName().equals("超级管理员") || role.getRoleName().equals("管理员")) {
            UserInfo userInfo = this.getById(userId);
            Integer status = userInfo.getStatus();
            if (status == 0) {
                userInfo.setStatus(1);
            }else {
                userInfo.setStatus(0);
            }

            this.updateById(userInfo);
            return PermissionResult.ERROR(200, "加入成功");
        }

        return PermissionResult.ERROR(400, "您没有权限");
    }

    @Override
    /**
     * @description:删除用户
     * @author: muhaoyang
     * @date: 2025/1/6 10:11
     * @param: [userId]
     * @return: com.zhentao.model.common.dtos.ResponseResult
     **/
    public ResponseResult deleteUser(Integer userId) {
        if (userId == null) {
            return ResponseResult.errorResult(400,"参数错误");
        }
        TbRole role = getRole();
        if (!role.getRoleName().equals("超级管理员")) {
            return ResponseResult.errorResult(400,"您没有权限");
        }
        boolean b = this.removeById(userId);
        //删除该用户对应的角色
        sysUserRoleMapper.delete(Wrappers.<TbUserRole>lambdaQuery().eq(TbUserRole::getUserId, userId));
        if (b) {
            return ResponseResult.okResult("删除成功");
        }
        return ResponseResult.errorResult(400,"删除失败");
    }
}
